#!/usr/bin/env bash
# compile-codegen -- Generates files from the compiled code represented in JSON
##
# Author: Jaeho Shin <netj@cs.stanford.edu>
# Created: 2015-12-05
set -euo pipefail

: ${DEEPDIVE_NUM_PROCESSES:=$(nproc --ignore=1)}

# a handy barrier to not spawn too many codegen processes
num_active=0
wait_if_needed() {
    local pid=$!
    if [[ $num_active -ge $DEEPDIVE_NUM_PROCESSES ]]; then
        wait -n
        let num_active--
    fi
    let ++num_active
}
wait_all() {
    while [[ $num_active -gt 0 ]]; do
        wait -n
        let num_active--
    done
}

# translate codegen instructions in JSON into commands and run them in parallel
eval "$(jq -r '
( @sh "
{
    x=\(.path)
    echo >&2 \" run/$x (PID $BASHPID)\"
    # ensure parent dir exists
    xd=\"$(dirname \"$x\")\"
    mkdir -p \"$xd\"
    # move existing files/dirs out of the way
    if [[ -e \"$x\" ]]; then
        chmod +w \"$x\" \"$xd\" || true
        mv -f --no-target-directory \"$x\" \"$x\"~
    fi
"

+ (.content |
    def find_no_occurs(eof; repeat):
        if contains(eof * repeat) | not then eof * repeat
        else find_no_occurs(eof; repeat+1)
        end;
    "\(find_no_occurs("__EOF"; 1))__" as $EOF | "
    # write contents
    cat >\"$x\" <<'\''\($EOF)'\''
\(.)
\($EOF)
")

+ (.mode | if . then @sh "
    # adjust mode
    chmod \(.) \"$x\""
else ""
end)

# finally, make sure each codegen runs asynchronously
+ @sh "
} & wait_if_needed
"
)
')"

# wait for all asynchronous processes to finish
wait_all
